package main

import (
	"fmt"
	"go/ast"
	"go/parser"
	"go/token"
	"os"
	"path/filepath"
	"strings"

	"game-simple/internal/framework/auth/models"
)

// scanModulesForModels 从 web_module 和 h5_module 扫描所有模块，自动识别模型
func scanModulesForModels() error {
	fmt.Println("🔍 开始扫描模块中的模型...")

	// 扫描 web_module.go
	if err := scanModuleFile("internal/framework/web_module.go"); err != nil {
		fmt.Printf("⚠️  扫描 web_module.go 失败: %v\n", err)
	}

	// 扫描 h5_module.go
	if err := scanModuleFile("internal/framework/h5_module.go"); err != nil {
		fmt.Printf("⚠️  扫描 h5_module.go 失败: %v\n", err)
	}

	// 直接扫描所有 framework 下的模块（备用方案）
	scanAllFrameworkModules()

	return nil
}

// scanModuleFile 扫描模块文件，提取引用的模块
func scanModuleFile(filePath string) error {
	fset := token.NewFileSet()
	node, err := parser.ParseFile(fset, filePath, nil, parser.ParseComments)
	if err != nil {
		return err
	}

	// 查找所有导入的模块
	importedModules := make(map[string]bool)

	// 遍历导入声明
	for _, imp := range node.Imports {
		importPath := strings.Trim(imp.Path.Value, "\"")
		// 提取模块名（如 game-simple/internal/framework/auth -> auth）
		if strings.Contains(importPath, "game-simple/internal/framework/") {
			parts := strings.Split(importPath, "/")
			if len(parts) > 0 {
				moduleName := parts[len(parts)-1]
				// 跳过非模块目录
				if moduleName != "framework" && moduleName != "router" {
					importedModules[moduleName] = true
				}
			}
		}
	}

	// 对每个导入的模块，扫描其 models 目录
	for moduleName := range importedModules {
		modelsDir := filepath.Join("internal/framework", moduleName, "models")
		if err := scanModelsInDirectory(modelsDir, moduleName); err != nil {
			fmt.Printf("⚠️  扫描模块 %s 的模型失败: %v\n", moduleName, err)
		}
	}

	return nil
}

// scanAllFrameworkModules 扫描 framework 目录下的所有模块（备用方案）
func scanAllFrameworkModules() {
	frameworkDir := "internal/framework"

	entries, err := os.ReadDir(frameworkDir)
	if err != nil {
		return
	}

	for _, entry := range entries {
		if !entry.IsDir() {
			continue
		}

		moduleName := entry.Name()
		// 跳过非模块目录
		if moduleName == "router" || strings.HasSuffix(moduleName, "_module.go") {
			continue
		}

		modelsDir := filepath.Join(frameworkDir, moduleName, "models")
		if _, err := os.Stat(modelsDir); os.IsNotExist(err) {
			continue
		}

		scanModelsInDirectory(modelsDir, moduleName)
	}
}

// scanModelsInDirectory 扫描指定目录下的模型文件
func scanModelsInDirectory(modelsDir, moduleName string) error {
	entries, err := os.ReadDir(modelsDir)
	if err != nil {
		return err
	}

	for _, entry := range entries {
		if entry.IsDir() || !strings.HasSuffix(entry.Name(), ".go") {
			continue
		}

		filePath := filepath.Join(modelsDir, entry.Name())
		if err := parseModelsFromFile(filePath, moduleName); err != nil {
			continue
		}
	}

	return nil
}

// parseModelsFromFile 从文件中解析模型类型
func parseModelsFromFile(filePath, moduleName string) error {
	fset := token.NewFileSet()
	node, err := parser.ParseFile(fset, filePath, nil, parser.ParseComments)
	if err != nil {
		return err
	}

	// 确保是 models 包
	if node.Name.Name != "models" {
		return nil
	}

	// 遍历所有类型声明
	ast.Inspect(node, func(n ast.Node) bool {
		switch x := n.(type) {
		case *ast.TypeSpec:
			if structType, ok := x.Type.(*ast.StructType); ok {
				typeName := x.Name.Name

				// 检查是否是模型（以 Model 结尾或包含 gorm tag）
				if strings.HasSuffix(typeName, "Model") || hasGormTag(structType) {
					registerModelByPath(moduleName, typeName)
				}
			}
		}
		return true
	})

	return nil
}

// hasGormTag 检查结构体是否包含 gorm tag
func hasGormTag(structType *ast.StructType) bool {
	for _, field := range structType.Fields.List {
		if field.Tag != nil {
			tag := field.Tag.Value
			if strings.Contains(tag, "gorm:") {
				return true
			}
		}
	}
	return false
}

// registerModelByPath 根据模块名和类型名注册模型
func registerModelByPath(moduleName, typeName string) {
	// 构建包路径
	packagePath := fmt.Sprintf("game-simple/internal/framework/%s/models", moduleName)

	// 尝试创建模型实例
	model := createModelInstanceByPath(packagePath, moduleName, typeName)
	if model != nil {
		// 注册完整路径格式
		fullName := fmt.Sprintf("%s.%s", moduleName, typeName)
		modelRegistry[fullName] = model

		// 如果短名称不存在，也注册短名称
		if _, exists := modelRegistry[typeName]; !exists {
			modelRegistry[typeName] = model
		}

		fmt.Printf("  ✅ 发现模型: %s (可用名称: %s 或 %s)\n", fullName, fullName, typeName)
	}
}

// createModelInstanceByPath 根据包路径创建模型实例
func createModelInstanceByPath(packagePath, moduleName, typeName string) interface{} {
	// 使用已知的包路径映射
	switch packagePath {
	case "game-simple/internal/framework/auth/models":
		return createAuthModel(typeName)
		// 在这里添加更多模块
		// case "game-simple/internal/framework/user/models":
		//     return createUserModel(typeName)
	}

	return nil
}

// createAuthModel 创建 auth 模块的模型
func createAuthModel(typeName string) interface{} {
	// 使用已导入的 models 包（在文件顶部已导入）
	switch typeName {
	case "UserModel":
		return &models.UserModel{}
	default:
		return nil
	}
}
